package vip.xiaonuo.biz.modular.inventorycheck.service.impl;

import cn.hutool.core.date.DateUtil;
import com.itextpdf.text.*;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfWriter;
import org.apache.commons.lang3.StringUtils;
import vip.xiaonuo.biz.modular.inventorycheck.vo.BizInventoryCheckVO;
import vip.xiaonuo.biz.modular.inventorycheckreport.entity.BizInventoryCheckReport;

import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.stream.Collectors;

public class ReportPdfExporter {
    public static void generatePDF(BufferedOutputStream out, BizInventoryCheckVO inventoryCheck, java.util.List<BizInventoryCheckReport> reportList) throws DocumentException, IOException {
        //创建文件
        Document document = new Document();
        //建立一个书写器
        PdfWriter writer = PdfWriter.getInstance(document, out);
        //打开文件
        document.open();

        Font font = getChineseFont(12);
        font.setColor(BaseColor.DARK_GRAY);

        setTitle(document, font, inventoryCheck);
        setHeader(document, font, inventoryCheck);
        setNormalGoods(document, font, reportList, inventoryCheck);
        setAbnormalGoods(document, font, reportList, inventoryCheck);

        document.close();//关闭文档
        writer.close(); //关闭书写器
    }

    private static void setTitle(Document document, Font font, BizInventoryCheckVO inventoryCheck) throws DocumentException {
        font.setSize(20);
        Paragraph title = new Paragraph(String.format("%s%s的盘库报告", inventoryCheck.getCabinetInfoName(),
                StringUtils.isEmpty(inventoryCheck.getCabinetDoorName()) ? "" : inventoryCheck.getCabinetDoorName()), font);
        title.setAlignment(Element.ALIGN_CENTER);
        document.add(title);
    }

    private static void setHeader(Document document, Font font, BizInventoryCheckVO inventoryCheck) throws DocumentException {
        font.setSize(14);
        Paragraph createTime = new Paragraph(String.format("发起时间：%s", DateUtil.formatDateTime(inventoryCheck.getCreateTime())), font);
        document.add(createTime);
        document.add(new Paragraph(String.format("发起人：%s", inventoryCheck.getCreateUserName()), font));
        document.add(new Paragraph(String.format("报告生成时间：%s", DateUtil.formatDateTime(inventoryCheck.getReportTime())), font));
        document.add(new Paragraph(String.format("报告生成人：%s", inventoryCheck.getReportUserName()), font));
        document.add(new Paragraph(String.format("盘库对象：%s-%s-%s", inventoryCheck.getCabinetGroupName(), inventoryCheck.getCabinetInfoName(), inventoryCheck.getCabinetDoorName()), font));
        document.add(new Paragraph(String.format("地点：%s", inventoryCheck.getLocation()), font));
        document.add(new Paragraph(String.format("系统%s数：%s件", inventoryCheck.getGoodsType() == 0 ? "物品" : "试剂", inventoryCheck.getCurInventory()), font));
        document.add(new Paragraph(String.format("盘点%s数：%s件", inventoryCheck.getGoodsType() == 0 ? "物品" : "试剂", inventoryCheck.getChkInventory()), font));
    }

    private static void setNormalGoods(Document document, Font font, java.util.List<BizInventoryCheckReport> reportList, BizInventoryCheckVO inventoryCheck) throws DocumentException {
        java.util.List<String> inList = reportList.stream().filter(report -> report.getState() == 1)
                .map(report -> {
                    if (inventoryCheck.getGoodsType() == 0) {
                        return String.format("%s(%s)", report.getGoodsName(), report.getGoodsCode());
                    } else {
                        return String.format("%s(%sg/%sml)", report.getGoodsName(), report.getReagentAvlWeight(), report.getReagentAvlVolume());
                    }
                })
                .collect(Collectors.toList());

        java.util.List<String> outList = reportList.stream().filter(report -> report.getState() == 2)
                .map(report -> {
                    if (inventoryCheck.getGoodsType() == 0) {
                        return String.format("%s(%s)", report.getGoodsName(), report.getGoodsCode());
                    } else {
                        return String.format("%s(%sg/%sml)", report.getGoodsName(), report.getReagentAvlWeight(), report.getReagentAvlVolume());
                    }
                })
                .collect(Collectors.toList());

        int inCount = inList.size();
        int outCount = outList.size();

        document.add(Chunk.NEWLINE);
        font.setColor(new BaseColor(0, 128, 0));
        font.setStyle(Font.BOLD);
        font.setSize(16);
        Paragraph paragraph = new Paragraph(String.format("正常%s(%s件)", inventoryCheck.getGoodsType() == 0 ? "物品" : "试剂", inCount + outCount), font);
        document.add(paragraph);

        font.setColor(BaseColor.DARK_GRAY);
        font.setStyle(Font.NORMAL);
        font.setSize(14);
        setGoodsItem(document, font, String.format("在库%s(%s件)", inventoryCheck.getGoodsType() == 0 ? "物品" : "试剂", inCount), inList);
        setGoodsItem(document, font, String.format("借出%s(%s件)", inventoryCheck.getGoodsType() == 0 ? "物品" : "试剂", outCount), outList);
    }

    private static void setAbnormalGoods(Document document, Font font, java.util.List<BizInventoryCheckReport> reportList, BizInventoryCheckVO inventoryCheck) throws DocumentException {
        java.util.List<String> list3 = reportList.stream().filter(report -> report.getState() == 3)
                .map(report -> {
                    if (inventoryCheck.getGoodsType() == 0) {
                        return String.format("%s(%s)", report.getGoodsName(), report.getGoodsCode());
                    } else {
                        return String.format("%s(%sg/%sml)", report.getGoodsName(), report.getReagentAvlWeight(), report.getReagentAvlVolume());
                    }
                })
                .collect(Collectors.toList());

        java.util.List<String> list4 = reportList.stream().filter(report -> report.getState() == 4)
                .map(report -> {
                    if (inventoryCheck.getGoodsType() == 0) {
                        return String.format("%s(%s)", report.getGoodsName(), report.getGoodsCode());
                    } else {
                        return String.format("%s(%sg/%sml)", report.getGoodsName(), report.getReagentAvlWeight(), report.getReagentAvlVolume());
                    }
                })
                .collect(Collectors.toList());

        java.util.List<String> list5 = reportList.stream().filter(report -> report.getState() == 5)
                .map(report -> {
                    if (inventoryCheck.getGoodsType() == 0) {
                        return String.format("%s(%s)", report.getGoodsName(), report.getGoodsCode());
                    } else {
                        return String.format("%s(%sg/%sml)", report.getGoodsName(), report.getReagentAvlWeight(), report.getReagentAvlVolume());
                    }
                })
                .collect(Collectors.toList());

        java.util.List<String> list6 = reportList.stream().filter(report -> report.getState() == 6)
                .map(report -> {
                    if (inventoryCheck.getGoodsType() == 0) {
                        return String.format("%s(%s)", report.getGoodsName(), report.getGoodsCode());
                    } else {
                        return String.format("%s(%sg/%sml)", report.getGoodsName(), report.getReagentAvlWeight(), report.getReagentAvlVolume());
                    }
                })
                .collect(Collectors.toList());

        java.util.List<String> list7 = reportList.stream().filter(report -> report.getState() == 7)
                .map(report -> {
                    if (inventoryCheck.getGoodsType() == 0) {
                        return String.format("%s(%s)", report.getGoodsName(), report.getGoodsCode());
                    } else {
                        return String.format("%s(%sg/%sml)", report.getGoodsName(), report.getReagentAvlWeight(), report.getReagentAvlVolume());
                    }
                })
                .collect(Collectors.toList());

        document.add(Chunk.NEWLINE);
        font.setColor(BaseColor.RED);
        font.setStyle(Font.BOLD);
        font.setSize(16);
        document.add(new Paragraph(String.format("异常%s(%s件)", inventoryCheck.getGoodsType() == 0 ? "物品" : "试剂",
                list3.size() + list4.size() + list5.size() + list6.size() + list7.size()),
                font));

        font.setColor(BaseColor.DARK_GRAY);
        font.setStyle(Font.NORMAL);
        font.setSize(14);
        setGoodsItem(document, font, String.format("实物在库系统不在库(%s件)", list3.size()), list3);
        setGoodsItem(document, font, String.format("实物不在库系统在库(%s件)", list4.size()), list4);
        setGoodsItem(document, font, String.format("实物存放处和系统存放处不一致(%s件)", list5.size()), list5);
        setGoodsItem(document, font, String.format("已报废未出库(%s)", list6.size()), list6);
        setGoodsItem(document, font, String.format("未扫码入库(%s)", list7.size()), list7);
    }

    private static void setGoodsItem(Document document, Font font, String title, java.util.List<String> items) throws DocumentException {
        Paragraph paragraph = new Paragraph(title, font);
        paragraph.setSpacingBefore(20);
        paragraph.setSpacingAfter(20);
        document.add(paragraph);
        if (items.isEmpty()) {
            Paragraph none = new Paragraph("无", font);
            paragraph.setSpacingBefore(30);
            paragraph.setSpacingAfter(30);
            none.setIndentationLeft(40);
            document.add(none);
        } else {
            setOrderedList(document, items);
        }
    }

    /**
     * 中文字体,解决中文不能显示问题
     *
     * @param fontSize font size
     * @return
     * @throws IOException
     * @throws DocumentException
     */
    private static Font getChineseFont(int fontSize) throws IOException, DocumentException {
        BaseFont baseFont = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
        Font font = new Font(baseFont);
        font.setColor(BaseColor.BLACK);
        font.setSize(fontSize);
        return font;
    }

    private static void setOrderedList(Document document, java.util.List<String> items) throws DocumentException {
        List orderedList = new List(List.ORDERED);
        items.forEach(item -> orderedList.add(new ListItem(item)));
        orderedList.setIndentationLeft(40);
        document.add(orderedList);
    }
}
